package com.wuxx.quartz.service;

import com.wuxx.quartz.QuartzTaskManager;
import com.wuxx.quartz.entity.STaskInfo;
import com.wuxx.quartz.job.QuartzTaskJob;
import com.wuxx.quartz.model.CronTimingModel;
import com.wuxx.quartz.model.IntervalTimingMode;
import com.wuxx.quartz.model.TimingModel;
import com.wuxx.quartz.model.TriggerType;
import org.nutz.dao.Cnd;
import org.nutz.dao.Condition;
import org.nutz.dao.Dao;
import org.nutz.dao.sql.Criteria;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.quartz.SchedulerException;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * 定时任务操作
 * @author wuxx
 * @date 2023-05-06 14:19
 */
@IocBean
public class TaskService {
    private static Logger log = LogManager.getLogger(TaskService.class);

    @Inject
    Dao dao;
    @Inject
    QuartzTaskManager quartzTaskManager;




    /**
     * 列表查询信息
     * @return
     */
    public List<STaskInfo> list(NutMap nm){
        Condition c = getComCri(nm);
        return this.dao.query(STaskInfo.class, c);
    }

    public STaskInfo info(NutMap nm){
        Condition c = getComCri(nm);
        return this.dao.fetch(STaskInfo.class, c);
    }

    /**
     * 列表查询条件
     * @param nm 参数
     * @return
     */
    protected Criteria getComCri(NutMap nm) {
        Criteria cri = Cnd.cri();
        if(Objects.isNull(nm)){
            //添加查询条件
            if (nm.has("oderDesc")) {
                cri.getOrderBy().desc(nm.getString("oderDesc"));
            }
            if (nm.has("taskEnName")) {
                cri.where().and("taskEnName", "=", nm.getString("taskEnName"));
            }
            if (nm.has("taskGroups")) {
                cri.where().andIn("taskGroup",  nm.getString("taskGroups").split(","));
            }
            if (nm.has("delFlag")) {
                cri.where().and("delFlag", "=", nm.getBoolean("delFlag"));
            }
        }
        return cri;
    }

    /**
     * 根据状态查询任务列表
     * @param status 0停止 1运行中 2暂停
     * @return
     */
    public List<STaskInfo> getTaskListByStatus(String status){
        return this.dao.query(STaskInfo.class, Cnd.where("delFlag", "=", true).and("status","=",status));
    }

    /**
     * 修改任务
     * @param sTaskInfo 任务对象
     * @return int
     */
    public int updateTask(STaskInfo sTaskInfo){
        sTaskInfo.setUpdateTime(new Date());
        return this.dao.update(sTaskInfo);
    }

    /**
     * 根据任务ID查询任务
     * @param taskId 任务ID
     * @return STaskInfo
     */
    public STaskInfo findTaskById(String taskId){
        return this.dao.fetch(STaskInfo.class, taskId);
    }

    /**
     * 根据任务ID修改任务状态
     * @param taskId 任务ID
     * @param status 任务状态
     * @return Boolean
     */
    public Boolean modifyTaskById(String taskId,String status){
        STaskInfo sTaskInfo = this.findTaskById(taskId);
//        sTaskInfo.setStatus(status);
        if("1".equals(status)) sTaskInfo.setTaskExecutionTime(new Date());
        return this.updateTask(sTaskInfo) > 0;
    }

    /**
     * 根据任务ID启动任务
     * @param taskId 任务ID
     * @param quartzParameter 任务启动参数
     * @return Boolean
     */
    public Boolean startTask(String taskId, Map<String,Object> quartzParameter){
        STaskInfo sTaskInfo = this.findTaskById(taskId);
        if(Objects.isNull(sTaskInfo)){
            log.info("任务"+taskId+"不存在！");
            return false;
        }
        return this.startTask(sTaskInfo,quartzParameter);
    }

    public Boolean startTask(STaskInfo sTaskInfo,Map<String,Object> quartzParameter){
        try {
            TimingModel timingModel = null;
            if(TriggerType.CRON.name().equals(sTaskInfo.getTaskType())){
                timingModel = new CronTimingModel((Class<? extends QuartzTaskJob>) Class.forName(sTaskInfo.getTaskClass()),
                        sTaskInfo.getTaskEnName(), sTaskInfo.getTaskGroup(),
                        sTaskInfo.getTaskDescription(), quartzParameter, sTaskInfo.getTaskCron());
            }else {
                timingModel = new IntervalTimingMode((Class<? extends QuartzTaskJob>) Class.forName(sTaskInfo.getTaskClass()),
                        sTaskInfo.getTaskEnName(), sTaskInfo.getTaskGroup(),
                        sTaskInfo.getTaskDescription(), TriggerType.getTriggerTypeByName(sTaskInfo.getTaskType()),
                        quartzParameter,sTaskInfo.getTaskInterval(),sTaskInfo.getTaskRepeat());
            }
            quartzTaskManager.addTask(timingModel);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException |
                 SchedulerException | ClassNotFoundException e) {
            log.error("任务启动失败!", e);
            return false;
        }
        //修改任务状态
        sTaskInfo.setStatus("1");
        return this.updateTask(sTaskInfo)>1;
    }

    /**
     * 任务监控，实时控制任务状态
     * @return
     */
//    public void startTask(){
//        //查询停止的任务进行启动
//        List<STaskInfo> taskList = this.dao.query(STaskInfo.class,Cnd.where("delFlag", "=", false));
//        taskList.forEach(p -> {
//            String status = this.quartzTaskManager.getStatusName(p.getTaskEnName(), p.getTaskGroup());
//            if(!p.getStatus().equals(status)){
//                if("1".equals(p.getStatus())){
//                    //添加任务
//                    this.startTask(p);
//                    log.info(p.getTaskEnName()+"任务启动");
//                }else if("2".equals(p.getStatus())) {
//                    //暂停任务
//                    this.pauseTask(p);
//                    log.info(p.getTaskEnName()+"任务暂停");
//                }else if("0".equals(p.getStatus())) {
//                    //停止任务
//                    this.stopTask(p);
//                    log.info(p.getTaskEnName()+"任务停止");
//                }else {
//                    //异常任务，状态同步到数据库
//                    p.setStatus(status);
//                    this.updateTask(p);
//                    log.info(p.getTaskEnName()+"任务异常,任务状态:"+status);
//                }
//            }
//        });
//    }

    /**
     * 任务监控，实时控制任务状态
     */
    public void startStaticTask(String taskGroups){
        //如果是空默认启动第一组任务
        if(Objects.isNull(taskGroups)) return;
        NutMap nm = new NutMap();
        nm.put("taskGroups", taskGroups);
        nm.put("delFlag", "0");
        List<STaskInfo> taskList = list(nm);
        //查询停止的任务进行启动
        taskList.forEach(p -> {
            String status = this.quartzTaskManager.getStatusName(p.getTaskEnName(), p.getTaskGroup());
            if(!p.getStatus().equals(status)){
                if("1".equals(p.getStatus())){
                    //添加任务
                    this.startTask(p);
                    log.info(p.getTaskEnName()+"任务启动");
                }else if("2".equals(p.getStatus())) {
                    //暂停任务
                    this.pauseTask(p);
                    log.info(p.getTaskEnName()+"任务暂停");
                }else if("0".equals(p.getStatus())) {
                    //停止任务
                    this.stopTask(p);
                    log.info(p.getTaskEnName()+"任务停止");
                }else {
                    //异常任务，状态同步到数据库
                    p.setStatus(status);
                    this.updateTask(p);
                    log.info(p.getTaskEnName()+"任务异常,任务状态:"+status);
                }
            }
        });
    }

    /**
     * 根据任务ID启动任务
     * @param taskId 任务ID
     * @return Boolean
     */
    public Boolean startTask(String taskId){
        return this.startTask(taskId, new HashMap<>());
    }
    /**
     * 根据任务ID启动任务
     * @param sTaskInfo 任务ID
     * @return Boolean
     */
    public Boolean startTask(STaskInfo sTaskInfo){
        return this.startTask(sTaskInfo,new HashMap<>());
    }

    /**
     * 根据任务ID停止任务
     * @return Boolean
     */
    public Boolean stopTask(String taskId){
        STaskInfo sTaskInfo = this.findTaskById(taskId);
        if(Objects.isNull(sTaskInfo)){
            log.info("任务"+taskId+"不存在！");
            return false;
        }
        return this.stopTask(sTaskInfo);
    }

    public Boolean stopTask(STaskInfo sTaskInfo){
        try {
            quartzTaskManager.deleteTask(sTaskInfo.getTaskEnName(),sTaskInfo.getTaskGroup());
        } catch (SchedulerException e) {
            log.error("任务停止失败!", e);
            return false;
        }
        //修改任务状态
        sTaskInfo.setStatus("0");
        return this.updateTask(sTaskInfo)>0;
    }

    /**
     * 根据任务ID暂停任务
     * @return Boolean
     */
    public Boolean pauseTask(String taskId){
        STaskInfo sTaskInfo = this.findTaskById(taskId);
        if(Objects.isNull(sTaskInfo)){
            log.info("任务"+taskId+"不存在！");
            return false;
        }
        return this.pauseTask(sTaskInfo);
    }

    public Boolean pauseTask(STaskInfo sTaskInfo){
        try {
            quartzTaskManager.pauseTask(sTaskInfo.getTaskEnName(),sTaskInfo.getTaskGroup());
        } catch (SchedulerException e) {
            log.error("任务暂停失败!", e);
            return false;
        }
        //修改任务状态
        sTaskInfo.setStatus("2");
        return this.updateTask(sTaskInfo)>0;
    }



}
